#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include <future>
#include <thread>

namespace MyRpc
{
    namespace client
    {
        class Requestor
        {
        public:
            using ptr = std::shared_ptr<Requestor>;
            using RequsetorCallBack = std::function<void(const BaseMessage::ptr&)>;
            using AsyncResponse = std::future<BaseMessage::ptr>;
            struct RequestorDesc
            {
                using ptr = std::shared_ptr<RequestorDesc>;
                BaseMessage::ptr request;
                RType rtype;
                std::promise<BaseMessage::ptr> response;  // 处理的结果
                RequsetorCallBack callback;   // 处理的回调函数
            };
        // 这个方法是注册给desptcher接口的 用来接收消息的回复
        void onResponse(const BaseConnection::ptr& conn, const BaseMessage::ptr& msg)
        {
            // 首先查找RequestorDesc管理对象中是否有这个管理对象
            // LOG(DEBUGLEVEL, "select的id : %s", msg->id().c_str());
            auto it = selectRequestorDesc(msg->id());
            if(it.get() == nullptr)
            {
                // LOG(DEBUGLEVEL, "没有找到这个描述管理 无法处理");
                return;
            }
            // 开始处理
            if(it->rtype == RType::REQ_CALLBACK)
            {
                it->callback(msg);
            }
            else if(it->rtype == RType::REQ_ASYNC)
            {
                // 如果获取的应答不需要处理就直接进行设置进去结果就好
                it->response.set_value(msg);
            }
            else
            {
                LOG(DEBUGLEVEL, "请求类型未知!");
            }
            // 处理完结果之后删除这个RequestorDesc
            delRequestorDesc(msg->id());
        }
        // 异步进行获取结果
        bool send(const BaseConnection::ptr& conn, const BaseMessage::ptr& req, AsyncResponse& async)
        {
            auto it = newRequestorDesc(req, RType::REQ_ASYNC);
            if(it.get() == nullptr)
            {
                LOG(DEBUGLEVEL, "没有成功建立这个对象");
                return false;
            }
            // LOG(DEBUGLEVEL, "消息uuid和消息信息已经被添加!");
            bool flag = conn->send(req);
            if(flag == false)
            {
                LOG(DEBUGLEVEL, "消息发送失败");
                return false;
            }
            // LOG(DEBUGLEVEL, "消息发送成功!");
            async = it->response.get_future();
            return true;
        }
        // 同步进行获取结果
        bool send(const BaseConnection::ptr& conn, const BaseMessage::ptr& req, BaseMessage::ptr& rep)
        {
            AsyncResponse rsp_future;
            bool flag = send(conn, req, rsp_future);
            if(flag == false)
            {
                return false;
            }
            
            rep = rsp_future.get();
            return true;
        }
        // 回调获取结果
        bool send(const BaseConnection::ptr& conn, const BaseMessage::ptr& req, const RequsetorCallBack& cb)
        {
            auto it = newRequestorDesc(req, RType::REQ_CALLBACK, cb);
            if(it.get() == nullptr)
            {
                LOG(DEBUGLEVEL, "没有成功建立这个对象");
                return false;
            }
            conn->send(req);
            return true;
        }

        private:
            // 对这个unorder_map进行管理
            RequestorDesc::ptr newRequestorDesc(const BaseMessage::ptr& msg, RType rtype, const RequsetorCallBack& cb = RequsetorCallBack())
            {
                std::unique_lock<std::mutex> lock(_mutex);
                RequestorDesc::ptr req = std::make_shared<RequestorDesc>();
                req->request = msg;
                req->rtype = rtype;

                if(rtype == RType::REQ_CALLBACK && cb)
                {
                    // 设置回调函数
                    req->callback = cb;
                }
                else
                {
                    // LOG(DEBUGLEVEL, "回调函数未设置!");
                }
                _response_manage.insert(std::make_pair(msg->id(), req));
                // LOG(DEBUGLEVEL, "id: %s", msg->id().c_str());
                return req;
            }
            bool delRequestorDesc(const std::string& rid)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _response_manage.erase(rid);
                return true;
            }
            RequestorDesc::ptr selectRequestorDesc(const std::string& rid)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _response_manage.find(rid);
                if(it == _response_manage.end())
                {
                    LOG(DEBUGLEVEL, "没有找到这个RequestorDesc");
                    return RequestorDesc::ptr();
                }
                // LOG(DEBUGLEVEL, "找到了这个RequestorDesc");
                return it->second;
            }
        private:
            std::mutex _mutex;
            std::unordered_map<std::string, RequestorDesc::ptr> _response_manage;
        };
    }
}